#include "event_board.h"
#include "event_timed_task.h"

TaskScheduleNode_t EventListCreate(void)
{
  TaskScheduleNode_t EventListNode = (TaskScheduleNode_t)EventMalloc(sizeof(TaskScheduleTable_t));
  if (EventListNode != NULL)
  {
    memset(EventListNode, 0, sizeof(TaskScheduleTable_t));

    EventListNode->NextItem = EventListNode;
    EventListNode->PreviousItem = EventListNode;
  }

  return EventListNode;
}

void EventListDestroy(TaskScheduleNode_t HeadNode)
{
  if (HeadNode != NULL)
  {
    TaskScheduleNode_t CurrectNode = HeadNode->NextItem;
    while (CurrectNode != HeadNode)
    {
      TaskScheduleNode_t TmpNoded = CurrectNode->NextItem;
      EventFree(CurrectNode);

      CurrectNode = TmpNoded;
    }

    EventFree(HeadNode);
  }
}

TaskScheduleNode_t EventListFind(TaskScheduleNode_t HeadNode, uint8_t Level)
{
  if (HeadNode != NULL)
  {
    TaskScheduleNode_t CurrectNode = HeadNode->NextItem;
    while (CurrectNode != HeadNode)
    {
      if (CurrectNode->AttachedParam.Level == Level)
        return CurrectNode;

      CurrectNode = CurrectNode->NextItem;
    }
  }

  return NULL;
}

TaskScheduleNode_t EventBuyNode(TaskAttachedParam_t *pFileTable)
{
  TaskScheduleNode_t Node = NULL;

  if (pFileTable != NULL)
  {
    Node = (TaskScheduleNode_t)EventMalloc(sizeof(TaskScheduleTable_t));
    if (Node != NULL)
    {
      memset(Node, 0, sizeof(TaskScheduleTable_t));

      Node->NextItem = NULL;
      Node->PreviousItem = NULL;

      Node->AttachedParam.Level = pFileTable->Level;
      Node->AttachedParam.Timeout = pFileTable->Timeout;
      Node->AttachedParam.AutoDestroy = pFileTable->AutoDestroy;
      memcpy(Node->AttachedParam.Param, pFileTable->Param, EVENT_TASK_ATTACHED_PARAM_SIZE);

      Node->AttachedParam.Exit = pFileTable->Exit;
      Node->AttachedParam.Execute = pFileTable->Execute;
    }
  }

  return Node;
}

bool EventInsertionNode(TaskScheduleNode_t Pos, TaskAttachedParam_t *pFileTable)
{
  if ((Pos != NULL) && (pFileTable != NULL))
  {
    TaskScheduleNode_t NewNode = EventBuyNode(pFileTable);

    if (NewNode != NULL)
    {
      TaskScheduleNode_t Parent = Pos->PreviousItem;

      Parent->NextItem = NewNode;
      NewNode->PreviousItem = Parent;
      NewNode->NextItem = Pos;
      Pos->PreviousItem = NewNode;

      return true;
    }
  }

  return false;
}

void EventListErase(TaskScheduleNode_t Pos)
{
  if (Pos != NULL)
  {
    TaskScheduleNode_t PosPrev = Pos->PreviousItem;
    TaskScheduleNode_t PosNext = Pos->NextItem;

    PosPrev->NextItem = PosNext;
    PosNext->PreviousItem = PosPrev;
    EventFree(Pos);
  }
}

bool EventListPushBack(TaskScheduleNode_t HeadNode, TaskAttachedParam_t *pFileTable)
{
  if (HeadNode != NULL)
  {
    TaskScheduleNode_t NewNode = EventBuyNode(pFileTable);

    if (NewNode != NULL)
    {
      HeadNode->PreviousItem->NextItem = NewNode;
      NewNode->PreviousItem = HeadNode->PreviousItem;
      NewNode->NextItem = HeadNode;
      HeadNode->PreviousItem = NewNode;

      return true;
    }
  }

  return false;
}

void EventListPopBack(TaskScheduleNode_t HeadNode)
{
  if (HeadNode != NULL)
  {
    if (HeadNode->PreviousItem != HeadNode)
    {
      TaskScheduleNode_t TmpNode = HeadNode->PreviousItem;

      HeadNode->PreviousItem = TmpNode->PreviousItem;
      TmpNode->PreviousItem->NextItem = HeadNode;
      EventFree(TmpNode);
      TmpNode = NULL;
    }
  }
}

bool EventListPushFront(TaskScheduleNode_t HeadNode, TaskAttachedParam_t *pFileTable)
{
  if ((HeadNode != NULL) && (pFileTable != NULL))
  {
    TaskScheduleNode_t NewNode = EventBuyNode(pFileTable);

    if (NewNode != NULL)
    {
      NewNode->NextItem = HeadNode->NextItem;
      NewNode->PreviousItem = HeadNode;
      HeadNode->NextItem->PreviousItem = NewNode;
      HeadNode->NextItem = NewNode;

      return true;
    }
  }

  return false;
}

void EventListPopFront(TaskScheduleNode_t HeadNode)
{
  if (HeadNode->NextItem != HeadNode)
  {
    TaskScheduleNode_t Node = HeadNode->NextItem;

    Node->NextItem->PreviousItem = HeadNode;
    HeadNode->NextItem = Node->NextItem;
    EventFree(Node);
    Node = NULL;
  }
}
